package org.visionlibrary.image.geomtric.model;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

import org.visionlibrary.image.geomtric.lines.Lines;
import org.visionlibrary.image.geomtric.util.Debug;


public abstract class TShape {
	protected List<Vector2d> segments;
	protected String name;
	
	public TShape(String name) {
		this.name = name;
		this.segments = new ArrayList<Vector2d>();
	}
	
	public String getName() {
		return name;
	}
	
	public List<Vector2d> getSegments() {
		return segments;
	}

	public abstract TShape copy(String name);

	public BufferedImage getAsBufferedImage(Color color, int padding) {
		Rectangle bounds = getBounds(padding);
		int dx = -Math.abs(bounds.x) + padding;
		int dy = -Math.abs(bounds.y) + padding;
		List<Vector2d> moved = Lines.move(segments, dx, dy);

		Point2d wieghtedCenter = org.visionlibrary.image.geomtric.lines.Lines
				.getWeightedCentroid(moved);
		Point2d normalCenter = org.visionlibrary.image.geomtric.lines.Lines
				.getCentroid(moved);
		BufferedImage img = Debug.Image.getImage(null, moved, null,
				bounds.width + padding, bounds.height + padding, color);
		Graphics g = img.getGraphics();
		g.setColor(Color.GREEN);
		g.fillRect(wieghtedCenter.getXAsInt() - 1,
				wieghtedCenter.getYAsInt() - 1, 3, 3);
		g.setColor(Color.BLACK);
		g.fillRect(normalCenter.getXAsInt() - 1, normalCenter.getYAsInt() - 1,
				3, 3);

		return img;
	}

	public java.awt.Rectangle getBounds() {
		return Lines.findBoundingRect(segments, 10);
	}

	public java.awt.Rectangle getBounds(int padding) {
		return Lines.findBoundingRect(segments, padding);
	}

	public TShape explode(double d) {
		Point2d centroid = center();
		for (int i = 0; i < segments.size(); i++) {
			Vector2d side = segments.get(i);
			Point2d projection = org.visionlibrary.image.geomtric.lines.Lines
					.pointProjectionOntoLineSegment(side, centroid);
			Vector2d direction = new Vector2d(centroid, projection);
			direction = direction.getNormalized();
			direction = Vector2d.scale(direction, d);
			Point2d cords = direction.coordinates();

			Point2d begin = Point2d.move(side.getFirst(), cords.x, cords.y);
			Point2d end = Point2d.move(side.getLast(), cords.x, cords.y);
			Vector2d nside = new Vector2d(begin, end);
			segments.set(i, nside);
		}

		java.awt.Rectangle bounds = getBounds();
		if (0 > bounds.x || 0 > bounds.y) {
			double dx = 0 > bounds.x ? Math.abs(bounds.x) : 0;
			double dy = 0 > bounds.y ? Math.abs(bounds.y) : 0;
			move(dx, dy);
		}

		return this;
	}

	public TShape rotate(double angle) {
		Point2d origin = org.visionlibrary.image.geomtric.lines.Lines
				.getWeightedCentroid(segments);
		for (int i = 0; i < segments.size(); i++) {
			Vector2d side = segments.get(i);
			Point2d begin = Point2d.rotate(side.getFirst(), origin, angle);
			Point2d end = Point2d.rotate(side.getLast(), origin, angle);
			Vector2d nside = new Vector2d(begin, end);
			segments.set(i, nside);
		}

		java.awt.Rectangle bounds = getBounds();
		if (0 > bounds.x || 0 > bounds.y) {
			double dx = 0 > bounds.x ? Math.abs(bounds.x) : 0;
			double dy = 0 > bounds.y ? Math.abs(bounds.y) : 0;
			move(dx, dy);
		}

		return this;
	}

	public TShape scale(double factor) {
		for (int i = 0; i < segments.size(); i++) {
			Vector2d side = segments.get(i);
			Point2d begin = Point2d.multiply(side.getFirst(), factor);
			Point2d end = Point2d.multiply(side.getLast(), factor);
			Vector2d nside = new Vector2d(begin, end);
			segments.set(i, nside);
		}

		return this;
	}

	public TShape move(double dx, double dy) {
		for (int i = 0; i < segments.size(); i++) {
			Vector2d side = segments.get(i);
			Point2d begin = Point2d.move(side.getFirst(), dx, dy);
			Point2d end = Point2d.move(side.getLast(), dx, dy);
			Vector2d nside = new Vector2d(begin, end);
			segments.set(i, nside);
		}

		return this;
	}

	public Point2d center() {
		return org.visionlibrary.image.geomtric.lines.Lines.getWeightedCentroid(segments);
	}

	public String toString() {
		return "name=" + name + ";count=" + segments.size() + ";bounds="
				+ getBounds();
	}
}